package com.cx.web;

import com.cx.config.LettuceRedisAdapter;
import com.cx.property.LettuceProperties;
import com.cx.utils.CacheConsts;
import com.cx.utils.ProtoStuffUtil;
import com.cx.utils.SerializeAdapter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Created by 舒建辉.
 * Date time 2019/3/21 21:45
 */
public abstract class BaseController<C> {

    private final LettuceProperties lettuceProperties;
    @Autowired
    private LettuceRedisAdapter lettuceRedisAdapter;

    public BaseController() {
        this.lettuceProperties = SerializeAdapter.lettuceProperties();
    }

    protected  <T> List<T> getList1stCache(String apikey, Class<T> targetClass){
        return lettuceRedisAdapter.getlist(apikey, targetClass);
    }

    protected  <T> T getObj1stCache(String apikey, Class<T> targetClass){
        return lettuceRedisAdapter.get(apikey, targetClass);
    }

    protected  <T> void putList1stCache(String apikey, List<T> target){
        lettuceRedisAdapter.setexlist(apikey, target, lettuceProperties.getCacheLevel1Ttl());
    }

    protected  <T> void putObj1stCache(String apikey, T target){
        lettuceRedisAdapter.setex(apikey, target, lettuceProperties.getCacheLevel1Ttl());
    }

    protected String apikey(String methodname, String[] paramnames, Object[] paramvals){
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        return apikey(((Class<C>)params[0]).getSimpleName(), methodname, paramnames, paramvals);
    }

    /**
     * api层缓存key
     * @param methodname
     * @param paramnames
     * @return
     */
    private static String apikey(String classname, String methodname, String[] paramnames, Object[] paramvals){
        StringBuffer sb = new StringBuffer(SerializeAdapter.lettuceProperties().cacheLevel1Pre() + classname);
        sb.append(":apis").append(StringUtils.isBlank(methodname)? "" : CacheConsts.SP+methodname);
        if(ArrayUtils.isNotEmpty(paramnames) && ArrayUtils.isNotEmpty(paramvals)) {
            Arrays.stream(paramnames).filter(p->null!=p).forEach(fieldname -> {
                sb.append(CacheConsts.SP+fieldname);
            });
            Arrays.stream(paramvals).filter(p->null!=p).forEach(paramval -> {
                if (paramval instanceof List) {
                    Collections.sort((List) paramval);
                }else if (paramval instanceof Object[]) {
                    Arrays.sort((Object[]) paramval);
                }else if(paramval instanceof Sort){
                    paramval = new String(ProtoStuffUtil.serialize(paramval));
                }
                sb.append(CacheConsts.SP + paramval.hashCode());
            });
        }

        return sb.toString();
    }
}
